#include "ble.h"
#include "common.h"

NimBLEServer *pServer = nullptr;              // 设备
NimBLEService *pService = nullptr;            // 服务
NimBLECharacteristic *pStateChar = nullptr;   // 通知写入 到手机端
NimBLECharacteristic *pControlChar = nullptr; // 读取手机 读取格式{1，1}  0X11
NimBLECharacteristic *pNAMEChar = nullptr;
NimBLECharacteristic *pledstatChar = nullptr; // 全开

NimBLEAdvertising *pAdvertising = nullptr;
NimBLEScan *pScan = nullptr;

bool is_ble_connected = false; // 全局连接状态标志
std::string target_ble_name = "xiaomi12";
std::string ble_name = "Blinker_BLE";
String resStr;

class ControlCallback : public NimBLECharacteristicCallbacks
{
    void onWrite(NimBLECharacteristic *pChar, NimBLEConnInfo &connInfo) override
    {
        std::string value = pChar->getValue();
        if (value.length() > 0)
        {
            if (value.length() == 2)
            {
                uint8_t relay_num = value[0];
                bool state = value[1];
                if (relay_num < 0 && relay_num > 5)
                {
                    Serial.println("引脚错误");
                }
                Serial.printf("{%x,%x}\n", relay_num, state);
                digitalWrite(pin_arr[relay_num - 1], state ? HIGH : LOW);
            }
        }
    }
} controlCallback;
class NaneCallback : public NimBLECharacteristicCallbacks
{
    void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo) override
    {
        std::string value = pCharacteristic->getValue();

        Serial.printf("Received Value: ");
        if (value.length() > 0)
        {
            if (String(value.c_str()) == "on")
            {
                for (size_t i = 0; i < 4; i++)
                {
                    digitalWrite(pin_arr[i], HIGH);
                }
            }
            else if (String(value.c_str()) == "off")
            {
                for (size_t i = 0; i < 4; i++)
                {
                    digitalWrite(pin_arr[i], LOW);
                }
            }
        }
    }
} naneCallback;
class ledstatCallback : public NimBLECharacteristicCallbacks
{
    void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo) override
    {
        std::string value = pCharacteristic->getValue(); //{}

        Serial.printf("Received Value: ");
        if (value.length() > 0)
        {
            for (int i = 0; i < value.length(); i++)
            {
                resStr += value[i];
            }
            Serial.println(resStr);
            target_ble_name = (resStr.c_str());
            resStr = "";
        }
    }
} ledstatCallback;
class ServerCallbacks : public NimBLEServerCallbacks
{
    void onConnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo) override
    {
        Serial.printf("Client address: %s\n", connInfo.getAddress().toString().c_str());
        is_ble_connected = true;
    }

    void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason) override
    {
        Serial.printf("Client disconnected - start advertising\n");
        is_ble_connected = false;
        NimBLEDevice::startAdvertising();
    }
} serverCallbacks;

class ScanCallbacks : public NimBLEScanCallbacks
{
    void onResult(const NimBLEAdvertisedDevice *advertisedDevice) override
    {
        Serial.printf("Advertised Device: %s \n", advertisedDevice->toString().c_str());

        if (advertisedDevice->getName() == target_ble_name && advertisedDevice->getRSSI() < 50)
        {
            digitalWrite(RELAYPIN_2, HIGH);

            pScan->stop();
        }
    }
} scanCallbacks;

void ble_init()
{

    Serial.println("Starting NimBLE Server");
    NimBLEDevice::init(ble_name);
    NimBLEDevice::setSecurityAuth(true, true, true);
    pServer = NimBLEDevice::createServer();
    pServer->setCallbacks(&serverCallbacks);
    pService = pServer->createService("1234");

    pStateChar = pService->createCharacteristic(
        "ABCD",
        NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);

    pControlChar = pService->createCharacteristic(
        "5678",
        NIMBLE_PROPERTY::WRITE);

    pControlChar->setCallbacks(&controlCallback);

    pNAMEChar = pService->createCharacteristic(
        "7891",
        NIMBLE_PROPERTY::WRITE);
    pNAMEChar->setCallbacks(&naneCallback);

    pledstatChar = pService->createCharacteristic(
        "1234",
        NIMBLE_PROPERTY::WRITE);
    pNAMEChar->setCallbacks(&ledstatCallback);
    pService->start();

    pAdvertising = NimBLEDevice::getAdvertising();
    pAdvertising->setName(ble_name);
    pAdvertising->addServiceUUID(pService->getUUID());
    pAdvertising->setAppearance(0x0540);
    pAdvertising->enableScanResponse(true);
    pAdvertising->start();

    pScan = NimBLEDevice::getScan();
    pScan->setScanCallbacks(&scanCallbacks);
    pScan->setActiveScan(true);
    pScan->setInterval(100);
    pScan->setWindow(99);
}

void notify_state_change(uint8_t relay_num, bool state)
{
    if (pStateChar && is_ble_connected)
    {
        uint8_t data[2] = {relay_num, state};
        pStateChar->setValue(data, 2);
        pStateChar->notify();
    }
}
void set_ble_name(std::string &name)
{
    ble_name = name;
}


void is_scan_star()
{
    if (pScan)
    {   
         Serial.println("Starting BLE scan...");
        pScan->clearResults(); // 清除之前的扫描结果
        pScan->start(5, false);
    }
}
void scan_stop(){
     if (pScan)
    {
        pScan->stop();
    }
}

std::string get_Characteristic_data(NimBLECharacteristic *pchar)
{
    if (pchar)
    {
        if (pchar == pControlChar && pControlChar)
        {
            return pControlChar->getValue();
        }
        else if (pchar == pNAMEChar && pNAMEChar)
        {
            return pNAMEChar->getValue();
        }
        else if (pchar == pledstatChar && pledstatChar)
        {
            return pledstatChar->getValue();
        }
        else
        {
            return "";
        }

    }
    return "";
}
